<template>
  <div class="container" id="container">
    <div id="mapbox" class="mapbox"></div>

    <!--左上角按钮-->
    <ul class="drawing-panel">
      <li class="bmap-btn bmap-circle" id="circle" title="重置" @click="resetOverlays">重置</li>
      <!--      <li class="bmap-btn" title="放大" @click="zoomHandle(true)">放大</li>-->
      <!--      <li class="bmap-btn" title="缩小" @click="zoomHandle(false)">缩小</li>-->
      <!--      <li class="bmap-btn" title="标记" @click="markHandle(556,485)">标记</li>-->
    </ul>

    <div class="layer-box">
      <h2>线路图层</h2>
      <el-tree
        :data="treeData"
        show-checkbox
        node-key="id"
        :default-expand-all="true"
        @check="checkChange">
      <span slot-scope="{ node, data }">
            <span class="custom-tree-node" :title="node.label">{{ node.label }}</span>
      </span>
      </el-tree>
    </div>

    <!--右上角信息窗-->
    <div class="tab-border-card" v-if="tabBorderCard.isShow && tabBorderCard.list.length>0">
      <el-tabs type="border-card" :tab-position="'right'">
        <el-tab-pane v-for="item in tabBorderCard.list" :label="item.title">
          <div class="border-card-cont">
            <h3><i class="el-icon-edit-outline"></i>{{ item.title }}</h3>
            <p v-for="lItem in item.cont"><b>{{ lItem.title }}：</b>{{ lItem.cont }}</p>
            <div v-if="item.case" v-html="item.case"></div>

          </div>
          <el-button size="small" type="primary" plain>
            <a class="more-btn" :href="item.moreUrl" target="_blank">点击显示更多信息</a></el-button>
        </el-tab-pane>
      </el-tabs>
    </div>

    <!--信息窗-->
    <div class="info-window" v-if="infoWindow.isShow"
         :style="{left: infoWindow.pixel.x+'px', top: infoWindow.pixel.y+'px'}">
      <h3>{{infoWindow.title}}:</h3>
      <div class="info-window-cont">
        {{infoWindow.cont}}
      </div>
    </div>

  </div>

</template>

<script>
// import echarts from "echarts";
import public_cable_distribution_box_data from "../assets/geojson/public_cable_distribution_box.json"
import testData from "../assets/testData/testData.json"
import gydlfjx from "../assets/imgs/gydlfjx.png"
import {nanoid} from 'nanoid'

// require("echarts/extension/bmap/bmap");

export default {
  data() {
    return {
      // echarts标记点数据
      pointsData: [
        // {
        //   name: "10kV新基步行街广场1号公用电缆分接箱",
        //   value: [113.59667708902926, 23.068816319642313],
        //   isWithinRange: false
        //   list: [
        //     {
        //       title: '标题1',
        //       cont: '内容1'
        //     },
        //     {
        //       title: '标题2',
        //       cont: '内容2'
        //     },
        //     {
        //       title: '标题3',
        //       cont: '内容3'
        //     }
        //   ]
        // },
      ],
      publicCableDistributionBoxData: public_cable_distribution_box_data,
      treeData: [
        {
          id: 1,
          label: '线路',
          children: [
            {
              id: 11,
              label: '线路一',
              type: 'polyline',
              point: [
                {
                  lon: 116.67509,
                  lat: 39.540839
                },
                {
                  lon: 116.686875,
                  lat: 39.534022
                },
                {
                  lon: 116.696865,
                  lat: 39.527427
                }
              ]
            },
            {
              id: 12,
              label: '线路二',
              type: 'polyline',
              point: [
                {
                  lon: 116.675126,
                  lat: 39.541367
                },
                {
                  lon: 116.670275,
                  lat: 39.537667
                },
                {
                  lon: 116.672718,
                  lat: 39.518549
                }
              ]
            },
            {
              id: 13,
              label: '线路三',
              type: 'polyline',
              point: [
                {
                  lon: 116.672754,
                  lat: 39.518271
                },
                {
                  lon: 116.691151,
                  lat: 39.518842
                },
                {
                  lon: 116.698769,
                  lat: 39.518814
                }
              ]
            }
          ]
        }
      ],
      myChart: null,
      bmap: null,
      drawingManager: null, // 鼠标绘制工具
      overlays: [], // 鼠标绘制工具画的覆盖物圆、连线
      testBmapData: testData.data,
      // 右上角窗口的显示隐藏
      tabBorderCard: {
        isShow: false,
        list: []
      },
      infoWindow:{
        isShow: false,
        title: '',
        cont: '',
        pixel:{
          x: 0,
          y: 0
        }
      }
    };
  },
  created() {
    // bmap标记点数据赋值
    this.treeData.push({
      id: 2,
      label: this.publicCableDistributionBoxData.name,
      children: []
    })
    this.publicCableDistributionBoxData.features.forEach(item => {
      const obj = {
        id: nanoid(),
        label: item.properties['名称'],
        type: 'marker',
        isWithinRange: false,
        point: [
          {
            lon: item.geometry.coordinates[0],
            lat: item.geometry.coordinates[1]
          }
        ],
        list: [
          {
            title: '剩余接口数量',
            cont: item.properties['剩余接口数量']
          }
        ]
      }
      this.treeData[1].children.push(obj)
    })

  },
  mounted() {
    this.initMap();
  },
  beforeDestroy() {
  },
  methods: {
    initMap() {
      // const mapContainer = document.getElementById('mapbox'); // 地图容器 DOM
      // mapContainer.addEventListener('contextmenu', e => {
      //   e.preventDefault();
      //   e.stopPropagation();
      // });
      //
      // this.myChart = echarts.init(document.getElementById("mapbox"));
      // let option;
      // this.myChart.setOption((option = {
      //       animation: false,
      //       bmap: {
      //         // 百度地图中心经纬度
      //         center: [116.680732, 39.532731],  // 廊坊师范学院
      //         // 百度地图缩放
      //         zoom: 17,
      //         // 是否开启拖拽缩放，可以只设置 'scale' 或者 'move'
      //         roam: true,
      //         // 百度地图的自定义样式
      //         // mapStyle: {style:'midnight'}
      //       },
      //       tooltip: {  // 右上角自定义信息窗内容
      //         trigger: 'item', // 触发类型，这里设置为item
      //         alwaysShowContent: false, // 是否永远显示提示框内容，默认情况下在移出可触发提示框区域后 一定时间 后隐藏，设置为 true 可以保证一直显示提示框内容
      //         backgroundColor: 'rgba(255,255,255,1)',
      //         extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);', // 额外附加到浮层的 css 样式，此为浮层添加阴影
      //         padding: [20, 20],
      //         confine: true, // 是否将 tooltip 框限制在图表的区域内
      //         formatter: function (params) {
      //           if (params.data.list && params.data.list.length > 0) {
      //             let boxCont = `<div style="width: 300px;height: 300px;overflow-y: auto;">
      //           <h2 style="border-radius: 5px; background: #d0e1ff;color: black;line-height: 20px;margin: 0;display: inline-block; padding: 6px 10px;font-size: 16px;font-weight: normal;white-space: normal">${params.name}</h2><dl>`
      //             const list = params.data.list;
      //             let ddHtml = '';
      //             for (let i = 0; i < list.length; i++) {
      //               ddHtml = ddHtml + `<dd style="margin: 8px 0; font-size: 14px; color: #000"><b>${list[i].title}：</b>${list[i].cont}</dd>`
      //             }
      //             boxCont = boxCont + ddHtml + `</dl></div>`
      //             return boxCont;
      //           }
      //         },
      //         position: {right: 10, top: 10}
      //       },
      //       visualMap: {
      //         show: false,
      //         top: "top",
      //         min: 0,
      //         max: 5,
      //         seriesIndex: 0,
      //         calculable: true,
      //         inRange: {
      //           color: ["blue", "blue", "green", "yellow", "red"],
      //         },
      //       },
      //       // ... 其他配置项
      //       series: [
      //         {
      //           type: "scatter",
      //           silent: false,
      //           // 使用百度地图坐标系
      //           coordinateSystem: "bmap",
      //           symbol: "image://" + require("../assets/imgs/gydlfjx.png"),
      //           data: this.pointsData,
      //           symbolSize: [50, 57], // 设置标记点的大小
      //           label: {
      //             show: true,
      //             formatter: "{b}",
      //             fontWeight: "bold",
      //             color: "rgba(0, 76, 169, 1)",
      //             fontSize: 14,
      //             // textBorderColor: "rgba(0, 0, 0, 1)",
      //             textShadowColor: "rgba(255, 255, 255, 1)",
      //             textShadowBlur: 1,
      //             textShadowOffsetX: 0.5,
      //             textShadowOffsetY: 0.5
      //           }
      //         }
      //       ]
      //     })
      // );
      //
      // // 获取百度地图实例，使用百度地图自带的控件
      // this.bmap = this.myChart.getModel().getComponent("bmap").getBMap();
      // bmap.addControl(new BMap.MapTypeControl());

      this.bmap = new BMap.Map("mapbox");
      this.bmap.centerAndZoom(new BMap.Point(116.680732, 39.532731), 17);
      this.bmap.enableScrollWheelZoom(true);

      // this.bmap.addEventListener('rightclick', (e) => {
      //   e.domEvent.preventDefault();  // 阻止默认右键菜单
      //   e.domEvent.stopPropagation(); // 阻止事件冒泡到绘制工具
      //   // this.drawingManager.close();
      //   console.log('右击坐标：', e.point.lng, e.point.lat);
      // });

      // 设置最小缩放值
      this.bmap.setMinZoom(10);
      // 设置最大缩放值
      this.bmap.setMaxZoom(18);

      this.setSourceMarkData();
      this.setDrawingManager();
    },
    // 实例化鼠标绘制工具 https://lbsyun.baidu.com/index.php?title=jspopular/guide/mouse2draw
    setDrawingManager() {
      this.drawingManager = new BMapLib.DrawingManager(this.bmap, {
        isOpen: false, //是否开启绘制模式
        enableDrawingTool: true, //是否显示工具栏
        drawingToolOptions: {
          anchor: BMAP_ANCHOR_TOP_LEFT, // 设置锚点在左上角
          offset: new BMap.Size(20, 20), // 偏移值
          drawingModes: [ // 工具栏上可以选择出现的绘制模式
            BMAP_DRAWING_CIRCLE
          ]
        },
        // 圆的样式
        circleOptions: {
          strokeColor: '#5E87DB',   // 边线颜色
          fillColor: '#5E87DB',     // 填充颜色。当参数为空时，圆形没有填充颜色
          strokeWeight: 2,          // 边线宽度，以像素为单位
          strokeOpacity: 1,         // 边线透明度，取值范围0-1
          fillOpacity: 0.2,         // 填充透明度，取值范围0-1
          strokeStyle: 'solid'      //边线的样式，solid或dashed。
        },
      });

      //添加鼠标绘制工具监听事件，用于获取绘制结果
      this.drawingManager.addEventListener("circlecomplete", (e, overlay) => {
        // console.log(e);
        // console.log(e.getCenter().lat); // 纬度23.062591
        // console.log(e.getCenter().lng); // 经度113.597144
        // console.log(e.getRadius() / 1000); // 半径：千米

        this.resetOverlays();
        this.overlays.push(overlay);

        this.treeData[1].children.forEach(item => {
          item.isWithinRange = this.isWithinRange(item.point[0].lat, item.point[0].lon, e.getCenter().lat, e.getCenter().lng, e.getRadius() / 1000)
        })
        const targetList = this.treeData[1].children.filter(item => item.isWithinRange)

        this.testBmapData.forEach(item => {
          item.isWithinRange = this.isWithinRange(item.value[1], item.value[0], e.getCenter().lat, e.getCenter().lng, e.getRadius() / 1000)
        })
        const sourceList = this.testBmapData.filter(item => item.isWithinRange);

        this.setMarkerStyleAndLine(targetList, sourceList);
      });
    },
    // 清除 圆 + 连线
    resetOverlays() {
      for (let i = 0; i < this.overlays.length; i++) {
        this.bmap.removeOverlay(this.overlays[i]);
      }
      this.overlays.length = 0;
      this.treeData[1].children.forEach(item => {
        item.isWithinRange = false;
      })
      this.testBmapData.forEach(item => {
        item.isWithinRange = false;
      })
      this.setMarkerStyleAndLine([], []);
    },
    /**
     * 设置 bmap标记点变色、连线
     * @param arr1 bmap标记点中 连线的目标点（左侧图层窗口中的点）
     * @param arr2 bmap标记点中 连线的起始点（返回数据中的点）
     */
    setMarkerStyleAndLine(arr1, arr2) {
      const markerIsWithinRangeList = [...arr1, ...arr2]
      this.bmap.getOverlays().forEach(item => {
        if (item.name) {
          if (item.name.indexOf('targetLabel') !== -1 || item.name.indexOf('sourceLabel') !== -1) {
            item.setStyle({
              color: 'rgba(0, 76, 169, 1)',
              border: "1px solid rgba(0, 76, 169, 1)",
            })

            const isWithinRange = markerIsWithinRangeList.some(m => item.name.indexOf(m.id) !== -1)
            if (isWithinRange) {
              item.setStyle({
                color: 'rgba(230, 0, 0, 1)',
                border: "1px solid rgba(230, 0, 0, 1)",
              })
            }
          }

          if (arr2.length > 0) {
            const isSource = arr2.findIndex(s => item.name.indexOf(s.id) !== -1);
            if (isSource !== -1 && !this.hasMouseoverEvent(item)) {
              item.addEventListener("mouseover", () => {
                this.tabBorderCard.isShow = true;
                this.tabBorderCard.list = arr2[isSource].list;
              });
            }
          } else if (item.name.indexOf('sourceMarker') !== -1) {
            item.removeEventListener("mouseover", () => {
            });
          }
        }
      })

      if (arr2.length > 0) {
        arr2.forEach(item2 => {
          arr1.forEach(item1 => {
            let lineArr = [new BMap.Point(item2.value[0], item2.value[1]), new BMap.Point(item1.point[0].lon, item1.point[0].lat)]
            // 创建折线
            const polyline = new BMap.Polyline(lineArr, {
              strokeColor: '#000',
              strokeWeight: 3,
              strokeOpacity: 1,
              strokeStyle: 'solid',
            });
            this.bmap.addOverlay(polyline); // 增加连线
            this.overlays.push(polyline);
          })
        })

        this.tabBorderCard.isShow = true;
        this.tabBorderCard.list = arr2[0].list;
      } else {
        this.tabBorderCard.isShow = false;
        this.tabBorderCard.list = []
      }
    },
    // 将返回数据标记在地图上
    setSourceMarkData() {
      this.testBmapData.forEach((item) => {
        // 创建Marker标注，使用图标
        const point = new BMap.Point(item.value[0], item.value[1]);
        const marker = new BMap.Marker(point);
        marker.name = 'sourceMarker' + item.id;
        this.bmap.addOverlay(marker);

        const label = new BMap.Label(item.name, { // 创建文本标注
          position: new BMap.Point(item.value[0], item.value[1]),
          offset: new BMap.Size(0, 0)
        })
        label.setStyle({  // 设置label的样式
          fontSize: '14px',
          color: 'rgba(0, 76, 169, 1)',
          border: "1px solid rgba(0, 76, 169, 1)",
        })
        label.name = 'sourceLabel' + item.id  // 命名文本，用于 改变颜色
        this.bmap.addOverlay(label);  // 增加文本
      })
    },
    // 共两个参数，依次为：传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象，包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
    checkChange(currentNode, treeChecked) {
      // console.log(currentNode);
      // console.log(treeChecked);

      const targetOverlays = ['polyline', 'polylineLabel', 'targetMarker', 'targetLabel']
      this.bmap.getOverlays().forEach(item => {
        if (item.name && targetOverlays.some(t => item.name.indexOf(t) !== -1)) {
          this.bmap.removeOverlay(item)  // 清除指定覆盖物（折线+文本+标记点）
        }
      })
      this.resetOverlays();

      const checkedKeys = treeChecked.checkedKeys;
      checkedKeys.forEach((item) => {
        const obj = this.findCheckItem(item, this.treeData);
        if (obj.point && obj.point.length > 0) {
          if (obj.type === 'polyline') { // 线
            // 创建折线
            const polyline = new BMap.Polyline(obj.point.map(pItem => new BMap.Point(pItem.lon, pItem.lat)), {
              strokeColor: 'red',
              strokeWeight: 5,
              strokeOpacity: 1,
              strokeStyle: 'dashed',
            });
            polyline.name = 'polyline'  // 命名折线，用于清除指定
            this.bmap.addOverlay(polyline); // 增加折线

            const label = new BMap.Label(obj.label, { // 创建文本标注
              position: new BMap.Point(obj.point[0].lon, obj.point[0].lat),
              offset: new BMap.Size(0, 0)
            })
            label.setStyle({  // 设置label的样式
              color: 'red',
              fontSize: '14px'
            })
            label.name = 'polylineLabel'  // 命名文本，用于清除指定
            this.bmap.addOverlay(label);  // 增加文本

          } else if (obj.type === 'marker') { // 点

            // 创建图标
            const myIcon = new BMap.Icon(gydlfjx, new BMap.Size(50, 57));
            // 创建Marker标注，使用图标
            const point = new BMap.Point(obj.point[0].lon, obj.point[0].lat);
            const marker = new BMap.Marker(point, {
              icon: myIcon
            });
            marker.name = 'targetMarker';
            this.bmap.addOverlay(marker);


            // 创建信息窗口对象
            // const infoWindow = new BMap.InfoWindow(obj.list[0].title + '：' + obj.list[0].cont, {
            //   width: 200,     // 信息窗口宽度
            //   height: 100,     // 信息窗口高度
            //   title: obj.label, // 信息窗口标题
            // });

            // 开启信息窗口——>鼠标划上时显示，一直显示可以改成click事件  mouseover
            marker.addEventListener("mouseover", (e) => {
              // this.bmap.openInfoWindow(infoWindow, point);
              this.infoWindow.isShow = true;
              this.infoWindow.title = obj.label;
              this.infoWindow.cont = obj.list[0].title + '：' + obj.list[0].cont;
              this.infoWindow.pixel = {x: e.pixel.x, y: e.pixel.y};
            });
            // 关闭信息窗口
            marker.addEventListener("mouseout", () => {
              // this.bmap.closeInfoWindow(infoWindow, point);
              this.infoWindow.isShow = false;
            });

            const label = new BMap.Label(obj.label, { // 创建文本标注
              position: new BMap.Point(obj.point[0].lon, obj.point[0].lat),
              offset: new BMap.Size(0, 0)
            })
            label.setStyle({  // 设置label的样式
              fontSize: '14px',
              color: 'rgba(0, 76, 169, 1)',
              border: "1px solid rgba(0, 76, 169, 1)",
              // borderWidth: '0',
              // background: "transparent"
            })
            label.name = 'targetLabel' + obj.id  // 命名文本，用于清除指定 或 改变颜色
            this.bmap.addOverlay(label);  // 增加文本
          }
        }
      })
    },
    findCheckItem(id, tree) {
      let obj = {}
      const blFun = (arr) => {
        if (arr && arr.length > 0) {
          arr.forEach((item) => {
            if (item.children && item.children.length > 0) {
              blFun(item.children)
            } else {
              if (item.id === id) {
                obj = {...item}
              }
            }
          })
        }
      }
      blFun(tree);
      return obj;
    },
    // 判断坐标(lat1,lon1)是否在坐标(lat2,lon2)的 radius千米范围内
    isWithinRange(lat1, lon1, lat2, lon2, radius) {
      const earthRadiusKm = 6371.0;
      const dLat = this.toRadians(lat2 - lat1);
      const dLon = this.toRadians(lon2 - lon1);

      lat1 = this.toRadians(lat1);
      lat2 = this.toRadians(lat2);

      const a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(lat1) * Math.cos(lat2) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);

      const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

      const distance = earthRadiusKm * c;

      return distance <= radius;
    },
    toRadians(degrees) {
      return degrees * Math.PI / 180;
    },
    // 判断元素上是否添加了mouseover事件
    hasMouseoverEvent(element) {
      try {
        element.addEventListener('mouseover', function () {
        }, {once: true});
        return false; // 没有抛出异常，说明没有添加过
      } catch (e) {
        return true; // 抛出异常，说明已经添加过
      }
    },
    // 缩放地图
    zoomHandle(type) {
      // console.log('缩放地图：', this.bmap.getZoom());
      if (type) {
        this.bmap.zoomIn();
      } else {
        this.bmap.zoomOut();
      }
    },
    // 将窗口坐标标记在地图上
    markHandle(x, y) {
      const pixel = new BMap.Pixel(x, y); // 窗口坐标（像素值）
      // const pixel = new BMap.Pixel(556, 485); // 窗口坐标（像素值）
      const point = this.bmap.pixelToPoint(pixel); // 将像素坐标转换为经纬度坐标
      // console.log("经度: " + point.lng + ", 纬度: " + point.lat);
      const point2 = new BMap.Point(point.lng, point.lat);
      const marker = new BMap.Marker(point2);
      this.bmap.addOverlay(marker);
    }
  },
};
</script>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  position: relative;

  #mapbox {
    height: 100vh;
    width: 100%;
  }
}

$tab-border-card-height: 350px;
::v-deep .tab-border-card {
  z-index: 9;
  position: fixed;
  right: 20px;
  top: 20px;
  background: #f4f4f4;
  box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
  width: 400px;
  height: $tab-border-card-height;
  overflow: hidden;

  .more-btn {
    color: unset;
  }

  .el-tabs--border-card {
    background: #FFF;
    border: none;
    box-shadow: none;
    height: 100%;
  }

  .el-tabs__item {
    padding: 12px 10px;
    height: auto;
    line-height: 17px;
    color: #303133;
    width: 38px;
    white-space: normal;
    writing-mode: vertical-rl;
    text-orientation: upright;
  }

  .el-tabs--right .el-tabs__header.is-right {
    margin-left: 0;
  }

  .border-card-cont {
    margin-bottom: 16px;
    height: $tab-border-card-height - 75px;
    overflow-y: auto;

    h3 {
      margin-bottom: 10px;
      font-size: 16px;

      i {
        margin-right: 5px;
      }
    }

    p {
      line-height: 20px;
      margin-bottom: 8px;
      font-size: 14px;
    }
  }
}

.layer-box {
  z-index: 9;
  position: fixed;
  left: 20px;
  top: 90px;
  background: #f4f4f4;
  box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
  width: 154px;
  height: calc(100% - 160px);
  overflow-y: auto;
  padding: 20px;

  h2 {
    text-align: center;
    margin: 0 0 16px 0;
  }

  .el-tree {
    background: #f4f4f4;
  }
}

.drawing-panel {
  z-index: 9;
  position: fixed;
  top: 20px;
  left: 149px;
  height: 47px;

  li {
    list-style: none;
    border-left: 1px solid #d2d2d2;
    float: left;
    width: 64px;
    height: 100%;
    background: #f4f4f4;
    cursor: pointer;
    text-align: center;
    line-height: 47px;
    color: #1e70ad;
    font-weight: bold;
    box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);

    &:hover {
      color: #f4f4f4;
      background: #1e70ad;
    }
  }
}

.custom-tree-node {
  font-size: 14px;
}

.info-window{
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.2);
  padding: 10px;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
  border-radius: 5px;
  font-size: 12px;
  z-index: 9;
  position: fixed;
  max-height: 300px;
  max-width: 500px;
  overflow-y: auto;
  h3{
    margin-bottom: 5px;
  }
}

</style>
